% Scripting guide

## Overview
This guide is intended as a reference for scripters who are implementing new features for the game.
Before scripting anything be sure to let me know you are scripting and what features you are going to attempt to implement.
This way I can ensure 2 people are not working on the same feature and also make sure you have access to the variables you need for your scripts.
You can contact me at support@BlindAudioGames.com.

## Documentation for your features
Since any features you add will be available to all map creators it is important to document them.
There is a section in the user guide where I will link to your documentation.
I use MarkDown to create the user guide and you may find this a helpful way to create html documentation.
You can provide your documentation as either text or html files.

## Setting up your environment
Whenever you receive a new copy of the game you should create a file in the Data for TB folder called game.config.
Put one line in this file that says "scripter".
This does 2 main things:

1. It enables the control + shift + R hot key to reload the current map which will also reload your scripts.
2. It stops your copy of the game from reporting script errors to my web server.
While it is helpful to know when people get errors so I can work to keep the game bug free, I don't need to see all the scripting errors you get while developing.

## Javascript
The scripting language is Javascript.
I chose this language because almost every professional programmer has been exposed to it at some point or other.
It is also a simple scripting language that uses dynamic types.
I use the Noesis Javascript.net library to host the javascript context.
And that library in turn uses the Google V8 engine which is the fastest Javascript engine available.

You should add a folder named after you in the Data for TB\\Scripts folder.
Then put your scripts inside that folder to keep them separate from other scripters' files.
The file extension you put on your scripts does not matter.  The game will parse all files inside the scripts folder as javascript.
You will need to set the load_scripts= flag in your map pack settings.txt file.
It takes the name of the folder you named after yourself.
For instance I use:

* load_scripts=ian_reed

I personally use Notepad++ for editing javascript.
I know it treats the files slightly differently if you name them with a .js extension.
It then knows they are javascript files and can attempt to help more.  For instance by having built in hot keys to comment or uncomment a block of code using javascript like comments.
This didn't work great for me but I'd love to hear if anyone else gets some of these niceties working.

## Common javascript mistakes
A very common javascript mistake is to not declare your variables using the var keyword.
When you forget to use this keyword then variables are declared in the global scope rather than the functions scope and you can get conflicts between variables of the same name that are used in different functions.

Also be aware that all scripters share the same environment so your scripts may conflict with others if you have declared the same function names.

Another common mistake in this javascript hosting environment is to get the letter casing incorrect when accessing variables.  The naming convention for C# (which is what the engine is written in) uses title casing.
If you're getting an error and things look right then you should double check that all the capitalization is correct.

## A few global functions
Here are the functions that are globally available:

* say("hello"), takes a string that is announced via text to speech.
* sound("wind.wav"), takes the name of a sound that will be played.
* music("beautiful_song.mp3"), changes the currently playing music to the filename you provide.
* randomSound("warrior_attack"), similarly to having a sound in a skill or unit file, picks a random sound with the given name and plays it.

## The global object
Because of the limitations of my current javascript library I can not serialize and deserialize the entire javascript context when saving and loading games.
So I have defined a special variable called "global" that I am able to save and load.
This object gets initialized to an empty object whenever you start a new map.
If you need to store counters or other data that needs to be remembered beyond the local scope of your function this is the place to do it.
I recommend setting a property with your name on the global object.
Then you can have a local variable g that points to your global property.
This way your variables will not conflict with anyone elses.
Here's an example.  Place this line in the global scope of your script.

<pre>
global.ian_reed = {};
</pre>

Then place this line at the top of each of your functions that need to alter your global object's properties.

<pre>
var g = global.ian_reed;
</pre>

And now you can reference the g variable in your functions and set and get properties from them like so.

<pre>
g.poison_counter += 1;
say(g.poison_counter);
</pre>

## The shared object
There are 2 ways to get at objects and functions that exist within the core game engine.
One of these ways is through variables that are passed into your function.
The other is through the "shared" object.
The variables passed in to your function are related to the event that you are responding to.
The shared object holds objects that are available at all times such as lists of all units or all tiles in the current map.
Here's an example of using the shared object:

<pre>
var tile = shared.Map.ReviewTile;
</pre>

See the object hierarchy section near the end of this guide to find out what properties and functions are currently exposed on the shared object and descendant objects.

## ## Event Subscriptions
You can define a special file called Event Subscriptions.txt in your scripts folder.
See the example in the Data for TB\\Scripts\\Ian Reed\\Non Script Files\\Event Subscriptions.txt file.
Each event line has the name of the event followed by the function that should be called for that event, followed by an optional JSON object notation to define arguments that will be passed to the function.

Valid event names are:

* on_map_key
* after_map_load
* after_create_unit
* after_unit_death
* after_perform_skill
* after_use_item
* after_effect_applied
* after_effect_removed
* after_effect_fizzled
* after_turn_ended
* after_turn_started
* override_handle_causers, this allows you to override how damage and healing are handled in the game.
* override_tb_team_ai
* override_tb_unit_ai
* after_item_equipped
* after_item_unequipped
* before_point_damage
* after_point_damage
* after_unit_move
* is_skill_or_item_usable_before_target
* is_skill_or_item_usable_with_target

## Example event subscriptions
I have some example functions that you might subscribe to each of these events.
Each event passes arguments that may be needed for that event and in the examples they are assigned to local variables with comments.
Override events return a JSON object with a handled boolean set to true or false to indicate whether this function decided to handle the event.
If true the engine will not run any other javascript or C# code setup to handle this event.
In this way you can truly override the logic and stop the engine from performing the built in logic.
I've prefixed the function names with my initials "ir_" and recommend you prefix them with your initials so we don't have naming conflicts between scripters.

<pre>
function ir_on_map_key(args) {
	var key = args.k;
	var mod = args.m;
	// You can compare the integer values stored in key and mod to the values defined in Built in\\Key Definitions.txt.
}
function ir_after_map_load(args) {
	var map = args.map;
}
function ir_after_create_unit(args) {
	var unit = args.unit;
}
function ir_after_unit_death(args) {
	var unit = args.unit;
}
function ir_after_perform_skill(args) {
	var source = args.source_unit;
	var target = args.target_unit;
	var targetTile = args.target_tile;
	var skill = args.skill;
	var success = args.success; // indicates whether the skill was successful after the chance roll.
}
function ir_after_use_item(args) {
	var source = args.source_unit;
	var target = args.target_unit;
	var targetTile = args.target_tile;
	var item = args.item;
	var success = args.success; // indicates whether the skill was successful after the chance roll.
}
function ir_after_effect_applied(args) {
	var source = args.source_unit;
	var target = args.target_unit;
	var targetTile = args.target_tile;
	var effect = args.effect;
}
function ir_after_effect_removed(args) {
	var source = args.source_unit;
	var target = args.target_unit;
	var targetTile = args.target_tile;
	var effect = args.effect;
}
function ir_after_effect_fizzled(args) {
	var target = args.target_unit;
	var tile = args.target_tile;
	var effect = args.effect;
}
function ir_after_turn_ended(args) {
	var units = args.ending_units; // a list of units on the team that is ending their turn.
}
function ir_after_turn_started(args) {
	var units = args.starting_units; // a list of units on the team that is starting their turn.
}
function ir_override_handle_causers(args) {
	// this function is responsible for dealing all damage and healing for any skill, item, or effect
	var effecter = args.effecter; // the skill, item, or effect causing damage or healing.
	var skill = args.skill; // the effecter, if it is a skill
	var item = args.item; // the effecter, if it is an item
	var effect = args.effect; // the effecter, if it is an effect
	var unit = args.cur_unit; // the unit using the skill or item, if any
	var target = args.target_unit; // the target of the skill, item, or effect
	var targetTile = args.target_tile; // the tile being effected, if in TB combat
	return { handled: true }; // handled indicates this script decided to handle it and the engine should not do any further perform skill logic.
}
function ir_override_tb_team_ai(args) {
	var units = args.units; // the list of units that need their AI run.
	var friends = args.friends;
	var enemies = args.enemies;
	return { handled: true }; // handled indicates this script decided to handle it and the engine should not do any further AI logic for this team.
}
function ir_override_tb_unit_ai(args) {
	// This method will get called multiple times for each unit until all units report that they did not do anything.
	// If the override_tb_team_ai event is handled then this function will never get called as the team level AI supersedes this logic.
	var unit = args.unit; // the single unit that needs it's AI run.
	var friends = args.friends;
	var enemies = args.enemies;
	return { handled: true, did_something: true }; // handled indicates this script decided to handle it and the engine should not do any further AI logic for this unit.
	// did_something indicates whether this unit performed an action or not.
}
function cb_after_item_equipped(e) {
	var unit = e.unit; // the unit that equipped the item
	var item = e.item; // the item equipped
}
function cb_after_item_unequipped(e) {
	var unit = e.unit; // the unit that unequipped the item
	var item = e.item; // the item unequipped
}
function cb_before_point_damage(e) {
	var source = e.source_unit; // the unit doing the damage
	var target = e.target_unit; // the unit being damaged
	var skillOrItem = e.effecter; // the skill or item doing the damage
	var point = e.point; // the point (as a point object) effected
	var amount = e.amount; // the damage that will be done
	return { handled: false }; // handled indicates this script decided to handle it and the engine should not do any further point damaging logic
}

function cb_after_point_damage(e) {
	var source = e.source_unit;
	var target = e.target_unit;
	var skillOrItem = e.effecter;
	var point = e.point;
	var amount = e.amount;
}
function cb_after_unit_move(e) {
	var unit = e.unit; // the unit that moved
	var added = e.unitAdded; // true if this unit was added to the map, false if it was just a movement
	var origin = e.origin; // the tile that this unit previously occupied. If added is true, this will be null
}
function cb_is_skill_or_item_usable_before_target(e) {
	var source_unit = e.source_unit; // the unit attempting to use this skill or item
	var effector = e.effector; // the skill or item trying to be used
	var suppress_speech = e.suppress_speech; // true on AI checking if something is useable turns, false otherwise. It's recommended you check this before saying anything in this function
	return { useable: true }; // return useable true to allow this skill or item to be used. false prevents its use
}
function cb_is_skill_or_item_usable_with_target(e) {
	var source_unit = e.source_unit; // the unit attempting to use this skill or item
	var target_unit = e.target_unit; // the target of this skill or item. Will be null when the target is a tile
	var target_tile = e.target_tile; // the target tile for this skill. Will have a value even when the taret is a unit
	var effector = e.effector; // the skill or item trying to be used
	var suppress_speech = e.suppress_speech; // true on AI checking if something is useable turns, false otherwise. It's recommended you check this before saying anything in this function
	return { useable: true }; // return useable true to allow this skill or item to be used. false prevents its use
}
</pre>

## Defining script flags
Script flags are a way for you to let map creators utilize your scripts in the same way that they use flags to utilize core engine features.
You can define a special file called Script Flag Definitions.txt in your scripts folder.
See the example in the Data for TB\\Scripts\\Ian Reed\\Non Script Files\\Script Flag Definitions.txt file.

There are a couple comments in the file that I'll repeat here. 
// each line has the flag name followed by the type.  Valid types are string, bool, int, float, percent, keys, function, and enum followed by a pipe and list of enums separated by commas. 
// You can optionally have a list of file types that the flag can be used in, separated by commas.  If left off the flag is valid in all files. 

Down the road the valid files might not be optional, I recommend specifying them as it will give map creators a friendly error when they accidentally use a script flag in the wrong file. 
Let me comment on each type: 

* string, used for textual data, can have spaces in it, if you want to do completely custom flag parsing this is a good one to use. 
* bool, as with normal flags just specifying the name of the flag sets it to true. 
You can also do flag_name false which sets it to false, since that is basically the default this is only helpful in inheritance scenarios. 
* int, whole numbers, negative numbers are supported. 
* float, decimal numbers, negative numbers are supported. 
* percent, expects this format: flag_name 52%, when you get the value the 52 will be 0.52.  Using the percent sign makes it more obvious to map creators about what this number means. 
* keys, uses the same format as the Keys.config flags, such as quest_menu control q.  There is a special javascript function that lets you check if the specified keys were pressed.  I still need to include this in TB but it already exists in the RPG, so remind me, smile. 
* function, This expects this format: flag_name function_name {}, note that this is similar to the last part of the old event syntax. There is also a javascript function for calling these functions that I still need to put into TB. 
* enum, this works just like string except if the map creator uses any value you did not provide as an option they receive an error. 
In the definitions file it looks like this: flag_name enum|option1,option2,option3 

## Accessing script flags from javascript
Each object that supports script flags has a new dictionary on it called ScriptFlags. 
Here's an example of me getting the announce_name script flag off of a unit in my testing.js file included with the game: 

<pre>
function announce_message(args) { 
	if (args.unit) { 
		if (args.unit.ScriptFlags.get("announce_name")) { 
			say(args.unit.FriendlyName); 
		} 
	} 
	say(args.message); 
} 
</pre>
So again that was 

<pre>
var val = unit.ScriptFlags.get("announce_name"); 
</pre>

If you try to get a script flag that was not defined in an object's file then null will be returned.

### Guidelines for script flags and event subscriptions
In general you will subscribe one function to each global event in the event subscriptions.txt file.
You should base the behavior of your scripts on script flags that map creators have defined on their files.
If they have not set any script flags your scripts probably shouldn't do anything.
This keeps control in the map creators hands so they can choose to use a feature you provide through script flags without getting an unwanted feature that occurs when your scripts are loaded regardless of what script flags are set.

## The Object Hierarchy
Each of the below sections lists the type of object in the heading tag followed by each property and function exposed on it in a bulleted list.
Note that Units and Structures are actually both the Unit type under the hood but that Structures have a boolean set to true so I can treat them differently in the few cases they need to work differently.

### IndexedName and FriendlyName
Most objects now have both an IndexedName and a FriendlyName.
The IndexedName is used for hash indexing and for comparison to see if 2 objects had the same file name and will be unique across objects created from different files.
The FriendlyName includes capitalization and is the form presented to players both visually and through speech.
The FriendlyName can be set to the same value between 2 files.
For instance you might have a floor terrain and a trapped floor terrain but set both of them to have the same friendly name of "Floor" so that players can not tell which tiles are trapped and which ones are not.
So the rule of thumb is to use IndexedName for comparisons and hash indexes, but FriendlyName for text to speech and visual text.
The Unit object has IndexedType and FriendlyType proeprties instead because it's Name property is used for naming units and was never based on the file name.

### Quirks of working with Dictionaries and Lists
When you get a List or Dictionary (hash for short) from the engine it will not work like a normal javascript array.
In fact any object obtained from the shared object will not work like a normal javascript object.
Specifically these objects can not have their properties enumerated by for looping over them as is normal in javascript.
Here's an example of what you can not do:

<pre>
var tiles = shared.Map.AllTiles;
for (var key in tiles) {
	say("tile " + shared.GetPos(tiles[key]));
}
</pre>

Instead when working with lists you must get their length and use a for loop that increments an indexer, such as the following:

<pre>
var tiles = shared.Map.AllTiles;
for (var i = 0; i < tiles.length; ++i) {
	say("tile " + shared.GetPos(tiles[i]));
}
</pre>

Here's an example of announcing all the keys and values of a dictionary.

<pre>
var g = shared.GetStorage("ian_reed");
var keys = g.keys;
for (var i=0; i < keys.length; i++) {
 var key = keys[i];
 var value = g.get(key);
 say(key + " = " + value);
}
</pre>

### List properties

* left and right bracket indexers such as shared.Map.AllTiles[0] which returns the first tile in the list.
* Count, returns a number indicating how many items are in the list.
* Add(newItem), takes a new item and adds it to the end of the list.
* Remove(oldItem), takes an item that is already in the list and removes it.
* length, same as Count but is more natural for javascript coders.
* push(newItem), same as the Add function but is more natural for javascript coders.

### Dictionary or hash properties

* get(key_name), returns the value for that key.
* set(key_name, new_value), sets the new value for that key name.
* keys, returns a list of keys that you can enumerate using the length and an indexer.  Make sure to use a lower case k as the version with a capital K returns a different object that is not useful in javascript.

### Shared Object properties

* Map of type Map
* ApplyEffect(string effect, Unit u, Tile t), this function applies an effect to the unit or tile based on whether the effect is intended for units or tiles.
* Calculate(string s), this function takes a string that indicates a solid number, range or dice roll and returns an integer calculated from the string.
* GetPos(Tile t), returns a string that represents the coordinates to be announced starting from 1 1 and paying attention to user preferences.
* PrepareForIndexing(string s), returns a string that is ready to be used to index into a hash or compare to an IndexedName.
* CreateUnit(string unitType), returns a unit object that is cloned from the base unit with the provided type name.
* GetStorage(name), returns a dictionary you can use to hold global variables that you want persisted across game saves and loads.  This is better than the global object because it can hold complex C# objects.
* GetUseableSkills(unit), returns a list of skills that the unit has enough points to use, useful for AI.
* TrySkill(skill, curUnit, targetUnit, targetTile), attempts to have the curUnit use the skill on the target unit or tile.  Returns true if the skill was valid and could actually be performed, false otherwise.  Also announces that there is a bug in the AI if it returns false.  I recommend escaping from AI logic when this returns false to avoid infinite loops where your AI thinks it can do something it can't.
* RemoveEffect(string effect, Unit u, Tile t): this function removes an effect from the unit or tile based on whether the effect is intended for units or tiles. If this is used to remove an effect successfully, the effect's `after_removed` event will trigger and the removal will be read aloud if the effect has the announce flag.
* GetEffectObjectByName(string effectName): Gets a map pack's effect object for a scripter without them needing to wait for it to be parsed into a function. If it doesn't exist, it will give a spoken warning and return null.
* GetSkillObjectByName(string skillName): Gets a map pack's skill object for a scripter without them needing to wait for it to be parsed into a function. If it doesn't exist, it will give a spoken warning and return null.
* GetItemObjectByName(string itemName): Gets a map pack's item object for a scripter without them needing to wait for it to be parsed into a function. If it doesn't exist, it will give a spoken warning and return null.
* GetUnitObjectByName(string unitName): Gets a map pack's unit object for a scripter without them needing to wait for it to be parsed into a function. If it doesn't exist, it will give a spoken warning and return null.
* AddSkillToUnit(Unit u, string skillName): Will grant the unit the skill with the given name. If verbose setting is turned on, this will be announced. 
* RemoveSkillFromUnit(Unit u, string skillName): Will remove the skill with the given name from the unit. If verbose setting is turned on, this will be announced. 
* ShareUnitUpdate(Unit u): In a multiplayer game, if this script function is called by the creater (or host) of a game, all other players will have this unit updated to that of the host. Updates that can be transmitted are (and are only), the team and the name.
* ShareUnitPointUpdate(Unit u, string[] pointNames):  For scripts that go changing the current or max values of points without use of DoDamageTo or DoRestoreTo or other in-engine methods. This allows other players in a multiplayer game to be notified of the point changes that have been made to the given unit. An array of point names can be given as the second argument to specify what points have been changed.

### Map properties

* Width of type int
* Height of type int
* ReviewTile of type Tile, read only.
* GetTile(int x, int y), returns the Tile at the coordinates.
* MoveReview(int x, int y), Moves the review cursor to the specified coordinates.
* AllTiles, returns a list of all tiles in the map.
* AllUnits, returns a list of all units in the map, this includes structures.
* AddUnit(Unit u, int x, int y), Adds a unit to the map at the specified coordinates.
* RemoveUnit(Unit u), Removes a unit from the map.
* MoveUnit(unit, x, y), moves the position of a unit that is already on the map.
* CurrentRound of type int, announces the current round number
* CurrentTurn of type int, announces the current turn number
* Teams of hash(number, Team), returns a hash with a numeric index of all the teams in the map pack. 
* CurrentTeam of type Team, the team whos turn it currently is. 
* PlayerTeam of type Team, the team representing the map's player_team. 
* GetAdjacentTiles(tile), returns a list of the tiles around the given tile. 
* GetDistance(x1, y1, x2, y2), calculates the distance between the tile at x1, y1 and the tile at x2, y2 and returns it as a number.

### Team properties

* Number of type, well, number, the numeric ID for the team. 
* Name of type string, the name of the team, as announced before each turn. 
* Friends, a list of team numbers representing this team's friends.
* Enemies, a list of team numbers representing this team's enemies. 

### Tile properties

* Selected of type unit, returns the selected unit or structure on the tile, read only
* X of type int, read only, it is a 0 based X index, when announced in game we add 1 to it.
* Y of type int, read only, it is a 0 based Y index that increases as tiles move down, when announced in game we add 1 to it.
* CanHold(Unit u), returns a boolean indicating if this tile can hold the unit, checks the units_per_tile and structures_per_tile flags to determine this.
* Units, a list of units on the tile.
* Structures, a list of structures on the tile.
* Effects, a list of effects on the tile.
* Inventory, an inventory object containing the items on the tile. 
* Terrain of type Terrain, represents the terrain on this tile
* IsValidDestinationFor(Unit u), returns a boolean indicating if this tile can be legitimately moved to by the passed in unit.

### Terrain properties

* IndexedName, the lower-case, underscore free, name based on the file name of the terrain. For none terrain, this will be empty, of course
* FriendlyName, the friendly name of the terrain.

### Unit properties

* ID of type int, the unique ID of the unit, useful for seeing if 2 units are the same or not.  Since reference comparisons don't work when comparing references of 2 objects given to you by the engine this ID needed to be added.
* Name of type string, the name of the unit if one is set
* IndexedType of type string, the type such as archer or warrior in a form ready for hash indexing and unique across files which makes it good for comparison.
* FriendlyType of type string, the type such as archer or warrior in a form presentable to sighted players.
* Tile of type Tile, the tile it currently occupies.
* Team of type int, set by the team flag.
* Points, which is a hash that takes a point name as an argument and returns a UnitPoint object. e.g. unit.Points.get("health");
* Effects, a list of effects on the unit
* GetName(), gets the formatted name of the unit including their team and name, ready to be spoken to players
* Dead of type bool, whether the unit is dead or not.
* DoDamageTo(Unit target, string amount, string pointName, string damageType): A function that will do damage to the target unit, taking into account the attackers mods and the defenders protections. The amount should be a valid integer, dice number or range. The pointname will be the point to be "damaged". DamageType is optional. But if supplied, the damage will be of that type. If null is specified, the map pack's default damage type will be used. The damage inflicted will be read allowed as though a skill caused this damage.
* DoDamageTo(Unit target, Hash<string, string> pointDamages, string damageType): Same as the other version of DoDamageTO, except that this one takes in a hash with the pointName as the key and the amount to damage as the value. For damaging several types of points at once. 
* DoRestoreTo(Unit target, string amount, string pointName): Similarly to DoDamageTo, this function will restore the given amount of the given point to the target, taking into account the unit's restore mods. 
* DoRestoreTo(Unit target, Hash<string, string> pointRestores): Similarly to the 2nd version of DoDamageTo, this function takes in a hash of pointnames and amounts to restore as it's 2nd argument. Allowing easier restoring of several points at once. Needless to say, this function otherwise works identically to the 1st version of DoRestoreTo.
* AllFlags, returns a hash of all the flags on the unit, including the ones set in the file and the extended flags that may be set on the map. Accessible the same as other hashes, i.e unit.AllFlags.get("description")
* Inventory, an inventory object containing the items in the unit's inventory. This will not include equipped items.
* GetEquippedItems(), returns a list of all items the unit has equipped.
* Flying of type boolean, whether the unit is a flying unit. Does not include effects.
* IsFlying(), returns a boolean stating if the unit is flying (either through having Flying set on itself or having a flying effect)

### UnitPoint properties

* Current of type int, the current amount of the point the unit has.
* Max, The maximum value the point can have except when adjusted by a skill with the ignore_max flag.
* LookupName, the name of the point as used to look it up in the Points hash. 

### Skill, item and effect common properties

* IndexedName, the lower-case, underscore free, name based on the file name of the skill.
* FriendlyName, the friendly name of the skill.
* AllFlags, returns a hash of all the flags on this object, with the flag name as the key.

### Effect properties

* RoundExpires of type int, the round number this effect will expire
* TurnExpires of type int, the turn number this effect will expire
* Hidden of type bool, whether this effect is hidden from the unit info announcement.

### Inventory properties

* Items, a list of items contained in this inventory
* Add(item): Adds the given item to the inventory
* CreateAndAddItem(string type): Creates a new item of the given type and adds it to the inventory, as well as returning it from the function. 

### Item properties

* EquipSlots, a list of strings containing the various equip slots of this item
* EquipTypes, a list of strings of all the equip types of this item
* Quantity, a number representing how many of this item there are
* Stackable, a boolean indicating whether this item is one that should be allowed to have a quantity greater than 1
* Equippable, a boolean indicating whether this is an item that can be equipped
* Useable, a boolean indicating if this is an item that should be used

## Old Event style
The old events are similar to flags and are defined in the same area as flags.
I'm trying to move away from these old events and toward the new event subscription and script flags because I think they make a better experience for map creators.
The old events must be on their own line unlike flags and you can only have one event per line.
The name of the event and the object it is added to define when the event will occur.
Each event can have multiple functions subscribed to it.
You do this by defining each new event subscription on a new line.

Here's an example of an event that can be placed in the default map flags file:

<pre>
on_key=set_point@ { key: x_key, mod: shift_mod, pointname: "health", value: "5r15" }
</pre>

on_key is the name of the event.
set_point is the name of the function that will be called when the event occurs.
Everything after the @ sign is JSON (Javascript object notation).
The JSON defines the initial properties for the object that will be passed to your function.
This is the perfect place for map creators to specify input to your function.
This JSON object will have game engine defined properties added to it based on which event is called.

In my functions I call the parameter args but you can give it any name you like.

### The Map on_key event
The on_key event allows you to hook into any key press the user makes.
I recommend letting the map creator specify which key combination they want in the JSON parameters.
You can see some examples of on_key events in use in my testing.js file.
You will also find the key_definitions.txt file helpful for using friendly names that correspond with the key numbers.

The on_key event gets these properties passed by the engine into it's local object:

* k, the number of the key pressed.
* m, The numbers of the modifiers pressed and bitwise ored together.  Modifiers are control, shift and alt.

### The skill after_perform event
This event is defined on skills and occurs after that skill has been used.
This gives you a place where you can make additional changes to the source or target unit after the engine has done all the things it supports.

The after_perform event gets these local properties:

* source_unit, the unit that performed the skill.
* target_unit, the unit that was the target of the skill.
* target_tile, the tile that was the target of the skill.  Useful for skills that target tiles instead of units.
* skill, the skill used.
* success, a boolean indicating whether the skill succeeded or failed due to the chance= flag.

### The effect after_applied event
This event is defined on effects and occurs after that effect has been applied to a unit or tile.

The event gets these local properties:

* source_unit, the unit that performed the skill that caused the effect, if any.
* target_unit, the unit that the effect was applied to.
* target_tile, the tile that was the target of the skill that caused the effect, can be passed even when the effect is only applied to units.
* effect, the effect applied.

### The effect after_removed event
This event is defined on effects and occurs after that effect has been removed through the use of a skill or item.
This does not occur when the effect fizzles because it's time duration expires.

The event gets these local properties:

* source_unit, the unit that performed the skill that removed the effect, if any.
* target_unit, the unit that the effect was removed from.
* target_tile, the tile that was the target of the skill that removed the effect, can be passed even when the effect is only removed from units.
* effect, the effect that was removed.

### The effect after_fizzled event
This event is defined on effects and occurs after that effect has fizzled due to it's duration expiring.
This does not occur when the effect is removed by a skill or item.

The event gets these local properties:

* target_unit, the unit that the effect fizzled from.
* target_tile, the tile that the effect fizzled from or the tile of the unit who's effect fizzled.
* effect, the effect that fizzled.

### The unit after_death event
This event is defined on units and occurs after that unit dies.

The event gets these local properties:

* unit, the unit that died.

### The unit after_create event
This event is defined on units and occurs after the unit is created.

The event gets these local properties:

* unit, the newly created unit.

## Closing remarks
First off I want to say thanks for being willing to contribute your time to create new features for the game.  It helps me and everyone else who plays or creates maps for Tactical Battle.

There are obviously many object properties that are not yet exposed.
As has been discussed this is because it makes the most sense for me to only expose things you actually need for your features.
This allows me to make more changes with a lower possibility of breaking your scripts.
It also allows me to cater the things I expose to make the most sense for how you are going to utilize them.
If you need access to something just let me know what you need it for and I'll see what I can do about getting it exposed.

Please realize that I may make your scripts obsolete at times.  I don't mean to hurt your feelings by doing this.  It will generally only be done if I feel I can give a better user experience because I'm able to access all the insides of the engine.

It has been a lot of work to add support for scripting but I think it will be a great addition to the game and I appreciate your help to make it a worthwhile feature.
Good luck!

Written by Ian Reed
